package com.googlecode.dgwt.client.dojox.data;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.googlecode.dgwt.client.dojo.Dojo;
import com.googlecode.dgwt.client.dojo.data.base.IndexedStore;
import com.googlecode.dgwt.client.dojo.data.base.MirroredStoreEngine;
import com.googlecode.dgwt.client.dojo.data.base.ModeledStore;
import com.googlecode.dgwt.client.dojo.data.base.TableStore;
import com.googlecode.dgwt.client.dojo.data.listener.ModelListener;
import com.googlecode.dgwt.client.dojo.data.model.StoreColumn;
import com.googlecode.dgwt.client.dojo.data.model.StoreModel;
import com.googlecode.dgwt.client.dojox.data.base.DataStoreBase;
import com.googlecode.dgwt.client.dojox.data.base.EmptyStore;
import com.googlecode.dgwt.client.dojox.data.model.ProxyColumn;
import com.googlecode.dgwt.client.dojox.data.model.ProxyModel;
import com.googlecode.dgwt.client.dojox.data.model.base.DataModelBase;

/**
 * @author wellsantos@wellsantos.com
 * @since 0.01
 */
public class ProxyStore<Item> extends DataStoreBase<Item,ProxyStore.ProxyStoreModel<Item>,ProxyColumn<Item, ?>> {

    public ProxyStore() {
        super(new ProxyStoreModel<Item>());
    }

    public ProxyStore(ModeledStore<Item> targetStore) {
        super(new ProxyStoreModel<Item>());
        setTargetStore(targetStore);
    }

    
    @Override
    protected MirroredStoreEngine<Item> createEngine(int initialCapacity) {
        return new MirroredStoreEngine<Item>(this);
    }

    @Override
    protected MirroredStoreEngine<Item> getEngine() {
        return (MirroredStoreEngine<Item>) super.getEngine();
    }

    public void setTargetStore(ModeledStore<Item> targetStore) {
        if (!Dojo.isEquals(getTargetStore(), targetStore)){            
            List<ModelListener<Item>> listeners = new ArrayList<ModelListener<Item>>(getModelListeners());
            
            for (Iterator<?> iterator = getModelListeners().iterator(); iterator.hasNext();){
                iterator.next();
                iterator.remove();
            }
            
            if (targetStore == null){
                this.getModel().setTargetModel(EmptyStore.<Item>getEmptyModel());
            } else {
                this.getModel().setTargetModel(targetStore.getModel());
            }
            
            getEngine().setMirroredStore(targetStore);

            for (ModelListener<Item> listener : listeners){
                addListener(listener);
            }
        }
    }
    
    public ModeledStore<Item> getTargetStore() {
        return (ModeledStore<Item>) getEngine().getMirroredStore();
    }

    @Override
    protected void setModel(ProxyStoreModel<Item> model) {
        if (this.getModel() != null){
            throw new UnsupportedOperationException("ProxyStore does not allow to change the model");
        }
        super.setModel(model);
    }

    @Override
    protected Class<?> getModelBaseClass() {
        return ProxyStoreModel.class;
    }

    @Override
    @SuppressWarnings("unchecked")
    public TableStore<Item> createMirror(StoreModel<Item, ?> model) {
        return new DataStore<Item>((DataStoreBase)this, (DataModelBase) model);
    }

    @Override
    public IndexedStore<Item> createMirror() {
        return createMirror(getModel());
    }

    public static class ProxyStoreModel<Item> extends ProxyModel<Item> {
        
        protected ProxyStoreModel(){
        }

        @Override
        protected void setTargetModel(StoreModel<Item, ? extends StoreColumn<Item, ?>> targetModel) {
            super.setTargetModel(targetModel);
        }        
        
    }
    
}
